package session;

## This file is part of the Simplemail project.
#  Copyright (c) 2008 the Simplemail Team (see authors).
# 
#  For the full copyright and license information, please view the COPYING
#  file that was distributed with this source code. You can also view the
#  COPYING file online at http://unixforum.org.ua/misc/COPYING.txt
# 
#  @copyright  (c) the authors
#  @author     Dmitriy Shilenko <rtyug@ukr.net>
#  @license    GPLv2 http://unixforum.org.ua/misc/COPYING.txt
#  @package    Panel Mailbox
#  @version    $Id: $

use strict;
use CGI::Carp qw(fatalsToBrowser);
use base 'func';
use CGI::Cookie;

sub new {
    my $self = shift->SUPER::new(@_);
    $self->dbi_connect if $self->can("dbi_connect");
    return $self;
}

sub _create_session {
    my $self = shift;

    my $session;
    my @rnd_txt = ( 0 .. 9, 'A' .. 'Z', 'a' .. 'z' );
    srand;

    for ( 0 .. 31 ) {
        my $s = rand(@rnd_txt);
        $session .= $rnd_txt[$s];
    }

    $self->{dbh}->do(
        qq{INSERT INTO session (session,
                 user,
                 time,
                 host,
                 ip,
                 forwarded ) VALUES (?, ?, ?, ?, ?, ?)
         }, undef, $session, '4', time, $self->{env}->{remote_host},
        $self->{env}->{remote_addr}, $self->{env}->{forwarded}
    );

    $self->{cookie}->{s_up} = $session;
    return $self;
}

sub _show_authorize_form {
    my $self = shift;

    my $expires;
    if ( $self->{session}->{user} > 5 ) {
        $expires = $self->{se}->{time_cookie_users};
    }
    else {
        $expires = $self->{se}->{time_cookie_admin};
    }

    $self->{session}->{cookie} = $self->{query}->cookie(
        -name    => 'session',
        -value   => $self->{cookie}->{s_up},
        -domain  => $ENV{'SERVER_NAME'},
        -expires => $expires
    );

    return $self;
}

sub _update_session {
    my $self = shift;

    $self->{dbh}->do( qq{UPDATE session SET time = ? WHERE session = ?},
        undef, time, $self->{cookies}->{session} );
    return $self;
}

sub fetch_error {
    my $self = shift;

    $self->{env}->{remote_addr} = $ENV{REMOTE_ADDR} || 'empty';
    $self->{env}->{remote_addr} =~ /(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})/g;
    $self->{env}->{remote_addr} = 'empty' unless $self->{env}->{remote_addr};

    $self->{env}->{remote_host} = $ENV{REMOTE_HOST} || 'empty';
    $self->{env}->{remote_host} = quotemeta $self->{env}->{remote_host};

    $self->{env}->{forwarded} = $ENV{HTTP_X_FORWARDED_FOR} || 'empty';
    $self->{env}->{forwarded} = quotemeta $self->{env}->{forwarded};

    my $id = $self->{dbh}->selectrow_arrayref(
        qq{SELECT count(*) AS max_error
                             FROM log_smail
                             WHERE 
                             action = ?
                             AND userid = ?
                             AND ip = ?
                             AND created > ?
                             }, undef, 'error_login2', '4', $ENV{REMOTE_ADDR},
        time - $self->{se}->{max_error_login_time}
    );

    if ( $id->[0] > $self->{se}->{max_error_login} ) {
        #return 0;
        ## 'The maximal amount of errors at an entrance is exhausted, make attempt after a while ';
    }
    return $self;
}

sub select_session {

    my $self = shift;

    $self->{cookies} = fetch CGI::Cookie;

    if ( $self->{cookies}->{session} ) {

        $self->{cookies}->{session} = $self->{cookies}->{session}->value;
        $self->{cookies}->{session} =~ s/\W+//g;
        $self->{cookies}->{session} =~ s/[<>\|\-&\.\\\/\0]//g;
        $self->{cookies}->{session} = 'empty'
          unless $self->{cookies}->{session};

        #    $cookies{session} = $dbh->quote($cookies{session});

        $self->{session} = $self->{dbh}->selectrow_hashref(
            qq{SELECT t1.user,
                                     t1.host,
                                     t1.ip,
                                     t1.forwarded,
                                     t2.name
                             FROM session AS t1,
                                 users AS t2
                             WHERE t1.session = ?
                             AND t1.user = t2.id
                             LIMIT 1
         }, undef, $self->{cookies}->{session}
        );

        if ( $self->{session} && $self->{session}->{user} != 4 ) {

            if (   $self->{session}->{ip} ne $self->{env}->{remote_addr}
                || $self->{session}->{host} ne $self->{env}->{remote_host}
                || $self->{session}->{forwarded} ne $self->{env}->{forwarded} )
            {

                $self->_create_session();

                $self->_show_authorize_form();
            }

            #} else {

            $self->_update_session();

            #}

        }
        elsif ( $self->{session} && $self->{session}->{user} == 4 ) {
            $self->_update_session();

            #  $self->_print_head_to_guest();
            #       $self->_show_authorize_form();

        }
        else {

            $self->_create_session();

            $self->_show_authorize_form();
        }
    }
    else {

        $self->_create_session();

        $self->_show_authorize_form();
    }

    return $self->{session};

    #return $self;
}

sub entrance2 {
    my $self = shift;

    $self->{session}->{filet} = 'entrance2';
    $self->insert_logsmail if $self->can("insert_logsmail");

    $self->{cookies} = undef;

    $self->{cookies} = fetch CGI::Cookie;

    if ( $self->{cookies}->{session} ) {

        $self->{cookies}->{session} = $self->{cookies}->{session}->value;
        $self->{cookies}->{session} =~ s /\W+//g;
        $self->{cookies}->{session} =~ s/[<>\|\-&\.\\\/\0]//g;
        unless ( $self->{cookies}->{session} ) {
            $self->{he}->{error_login2} = 1;
        }

        $self->{p}->{login} ||= $self->{he}->{error_login2} = 1;
        $self->{p}->{pass}  ||= $self->{he}->{error_login2} = 1;

        $self->{p}->{login} =~ s /[\W]//g;

        $self->{p}->{pass} =~ s /[\\\']/\\$1/g;

        my $sth = $self->{dbh}->prepare(
            'SELECT id,
                                    name,
                                    pass,
                                    active
                             FROM users
                             WHERE name = ? 
                             LIMIT 1'
        ) or die "Couldn't prepare statement: " . $self->{dbh}->errstr;
        $sth->execute( $self->{p}->{login} ) or die "Couldn't execute statement: " . $sth->errstr;
        my $id = $sth->fetchrow_hashref();
        $sth->finish();

        if ( $id && $id > 0 ) {

            if ( crypt( $self->{p}->{pass}, $id->{pass} ) ne $id->{pass} ) {

                $self->{he}->{no_pass} = 1;

                $self->{he}->{error_login2} = 1;
            }

            if (   defined( $id->{name} )
                && $id->{name} ne 'Admin'
                && $id->{active} == 0 )
            {
                $self->{he}->{no_active}    = 1;
                $self->{he}->{error_login2} = 1;
            }

            if ( $self->{he}->{no_active} != 1 && $self->{he}->{no_pass} != 1 )
            {

                $self->{dbh}->do(
                    qq{UPDATE session SET user = ? WHERE session = ?},
                    undef, $id->{id}, $self->{cookies}->{session} );
            }

        }
        else {
            $self->{he}->{error_login2} = 1;
        }

    }
    else {
        $self->{he}->{error_login2} = 1;
    }

    if ( $self->{he}->{error_login2} == 1 ) {
        $self->_error_login2();
    }
    else {
        print $self->{query}
          ->redirect( -uri => $self->{se}->{url}, -status => 301 );
    }

    return $self;
}

sub _error_login2 {
    my $self = shift;

    $self->{session}->{filet} = 'error_login2';
    $self->insert_logsmail if $self->can("insert_logsmail");

    $self->{he}->{ERRORUP} = 1;

    $self->{session}->{filet} = 'entrance';
    $self->SUPER::templ_hash(@_);

    return $self;
}

sub entrance {
    my $self = shift;
    $self->{session}->{filet} = 'entrance';
    $self->SUPER::templ_hash(@_);
    return $self;
}

sub exit2 {
    my $self = shift;
    $self->{session}->{filet} = 'exit2';
    $self->insert_logsmail if $self->can("insert_logsmail");

    my %cookies = fetch CGI::Cookie;
    
    if ( $cookies{'session'} ) {
    
        $cookies{'session'} = $cookies{'session'}->value;
        $self->{cookies}->{session} =~ s/\W+//g;
        $self->{cookies}->{session} =~ s/[<>\|\-&\.\\\/\0]//g;

        my $sth = $self->{dbh}->prepare(
            'UPDATE session SET user = ?
                           WHERE session = ?
                           '
        ) or die "Couldn't prepare statement: " . $self->{dbh}->errstr;
        $sth->execute( '4', $cookies{'session'} ) or die "Couldn't execute statement: " . $sth->errstr;
        $sth->finish();
;
    }

    print $self->{query}
      ->redirect( -uri => $self->{se}->{url}, -status => 301 );
    return $self;
}

sub DESTROY {
    my $self = shift;
    $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
}

1;
